package com.softWeakReference;

import java.lang.ref.PhantomReference;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
import java.util.Map;
import java.util.WeakHashMap;

//http://www.cnblogs.com/-OYK/archive/2011/10/24/2222874.html
public class SoftWeakReference {

	public static void main(String[] args) {
		
		try {
			explainCase();
			//test1();
			//test2();
			// test3();
			//test4();
			test5();
			// test6();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	public static void explainCase() throws InterruptedException{
		//hello对象是在堆里， str变量引用hello对象，str在栈中
		String str = new String("hello"); //①
		ReferenceQueue<String> rq = new ReferenceQueue<String>(); //②
		WeakReference<String> wf = new WeakReference<String>(str, rq); //③
		
		String str1=wf.get();
		System.out.println("str1: " + str1); // 输出hello
		
		str=null; //④取消"hello"对象的强引用
		System.gc();
		System.gc();
		System.gc();
		System.gc();
		System.gc();
		System.gc();
		Thread.sleep(1000);
		String str2=wf.get(); //⑤假如"hello"对象没有被回收，str1引用"hello"对象
		System.out.println("str2: " + str2);
		
		//假如"hello"对象没有被回收，rq.poll()返回null
		Reference<? extends String> ref=rq.poll(); //⑥
		System.out.println(ref);
	}

	/** 强引用，JVM的默认实现 
	 * 本章前文介绍的引用实际上都是强引用，这是使用最普遍的引用。
	 * 如果一个对象具有强引用，那就 类似于必不可少的生活用品，垃圾回收器绝不会回收它。
	 * 当内存空 间不足，Java虚拟机宁愿抛出OutOfMemoryError错误，使程序异常终止，
	 * 也不会靠随意回收具有强引用的对象来解决内存不足问题。
	 * */
	public static void test1() throws InterruptedException {
		Object obj = new Object();
		Object strong = obj;
		obj = null;
		System.gc();
		Thread.sleep(1000);
		System.out.println("strong=" + strong);
	}

	/**
	 * WeakReference 弱引用( 当所引用的对象在 JVM 内不再有强引用时,
	 *  GC 后weak reference 将会被自动回收)
	 *   弱引用与软引用的区别在于：只具有弱引用的对象拥有更短暂的生命周期。
	 *   在垃圾回收器线程扫描它 所管辖的内存区域的过程中，一旦发现了只具有弱引用的对象，
	 *   不管当前内存空间足够与否，都会回收它的内存。不过，由于垃圾回收器是一个优先级很低的线程， 
	 *   因此不一定会很快发现那些只具有弱引用的对象。弱引用可以和一个引用队列（ReferenceQueue）联合使用，
	 *   如果弱引用所引用的对象被垃圾回收，Java虚拟机就会把这个弱引用加入到与之关联的引用队列中。
	 * */
	public static void test2() throws InterruptedException {
		Object obj = new Object();
		WeakReference<Object> wr = new WeakReference<Object>(obj);
		obj = null;
		System.gc();
		Thread.sleep(1000);
		System.out.println("wr.get()=" + wr.get());
		System.out.println("wr=" + wr);
		wr.clear();
		System.out.println("w1111r=" + wr.get());
	}

	/**
	 * SoftReference和WeakReference 的特性基本一致， 最大的区别在于
	 * SoftReference 会尽可能长的保留引用直到 JVM 内存不足时才会被回收(虚拟机保证)
	 * 如果内存空间足够，垃圾回收器就不会回收它，如果内存空间不足了，就会回收这些对象的内存。
	 * 只要垃圾回收器没有回收它，该对象就可以被程序使用。软引用可用来实现内存敏感的高速缓存。
	 * */
	public static void test3() throws InterruptedException {
		Object obj = new Object();
		SoftReference<Object> sr = new SoftReference<Object>(obj);
		obj = null;
		System.gc();
		Thread.sleep(1000);
		System.out.println("sr.get()=" + sr.get());
	}

	/**
	 * PhantomReference Phantom Reference(虚引用)与WeakReference 和 SoftReference
	 * 有很大的不同, 因为它的 get()方法永远返回 null
	 * */
	public static void test4() throws InterruptedException {
		Object obj = new Object();
		ReferenceQueue<Object> rq = new ReferenceQueue<Object>();
		PhantomReference<Object> pr = new PhantomReference<Object>(obj, rq);
		System.out.println("pr.get()=" + pr.get());
	}

	/**
	 * ReferenceQueue：
	 * 
	 * @throws InterruptedException
	 */
	public static void test5() throws InterruptedException {
		Object obj = new Object();
		ReferenceQueue<Object> rq = new ReferenceQueue<Object>();
		WeakReference<Object> pr = new WeakReference<Object>(obj, rq);
		System.out.println("**pr.enqueue()=" + pr.enqueue());
		System.out.println("**pr.isEnqueued()=" + pr.isEnqueued());
		System.out.println("**pr=" + pr);
		System.out.println("**rq.poll()=" + rq.poll());
		obj = null;
		System.gc();
		// System.out.println("pr.enqueue()="+pr.enqueue());
		// System.out.println("**pr.isEnqueued()="+pr.isEnqueued());
		// System.out.println("pr="+pr);
		// System.out.println("rq.poll()="+rq.poll());
		// System.out.println("obj5="+obj);
	}

	/**
	 * 使用 WeakReference 作为 key， 一旦没有指向 key 的强引用, 
	 * WeakHashMap 在 GC 后将自动删除相关的entry
	 */
	public static void test6() throws InterruptedException {
		Map<Object, Object> map = new WeakHashMap<Object, Object>();
		Object key = new Object();
		Object value = new Object();
		map.put(key, value);

		key = null;

		// System.out.println("value="+value);
		// System.out.println("key="+key);
		// System.out.println("map.containsValue(value)="+map.containsValue(value));
		// System.out.println("map="+map);

		System.gc();
		Thread.sleep(1000);

		System.out.println("value=" + value);
		System.out.println("key=" + key);
		System.out.println("map.containsValue(value)=" + map.containsValue(value));
		System.out.println("map=" + map);
	}
}